import json
from gis.common import track_logging
from datetime import datetime

from django.http import QueryDict, JsonResponse, HttpResponse
from django.utils.deprecation import MiddlewareMixin

from gis.common.django_ext.views import PaginationResponse
from gis.common.exceptions import BizException
from gis.common.json import JsonEncoder
from gis.admin.const import ACTION
from gis.common.utils import get_request_ip, get_request_user_agent, shorten_user_agent

_LOGGER = track_logging.getLogger(__name__)


class ApiMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.DATA = QueryDict('')
        if request.method == 'GET':
            body = request.META['QUERY_STRING']
        else:
            body = request.body.decode()
        request.DATA = QueryDict(body)

    def process_exception(self, request, exception):
        if isinstance(exception, BizException):
            response = dict(
                status=exception.error_code.code,
                msg=exception.detail_message,
                timestamp=datetime.now(),
            )
        else:
            response = dict(
                status=-1,
                msg='内部错误，请联系管理员',
                timestamp=datetime.now(),
            )
        _LOGGER.exception('catched error %s in %s, uid:%s',
                          exception.__class__.__name__, request.path,
                          request.user_id if hasattr(request, 'user_id') else None)
        return JsonResponse(response, encoder=JsonEncoder, status=500)

    def process_response(self, request, response):
        if isinstance(response, (dict, list, PaginationResponse)):
            wrap_data = dict(
                status=0,
                msg="OK",
                timestamp=datetime.now(),
            )
            if isinstance(response, PaginationResponse):
                response = dict(total=response.total, items=response.items, **response.kwargs)
            wrap_data['data'] = response
            return JsonResponse(wrap_data, encoder=JsonEncoder)
        elif isinstance(response, str):
            return HttpResponse(response)
        elif response is None:
            return HttpResponse('')
        else:
            return response


class OperationLogMiddleware(MiddlewareMixin):
    def process_request(self, request):
        pass

    def process_exception(self, request, exception):
        pass

    def process_response(self, request, response):
        try:
            if isinstance(response, dict):
                handle_oper_record(request, response)
        except Exception as e:
            _LOGGER.info("OperationLogMiddleware  exception", exc_info=True)
        return response


def handle_oper_record(req, resp):
    if req.method not in ACTION:
        return
    try:
        resource_id = resp.get('id')
        action = ACTION[req.method]
        content = req.body.decode() if req.body else ''
        resource = req.permission_code if hasattr(req, 'permission_code') else None
        operator = req.user_id if hasattr(req, 'user_id') else None
        ip = get_request_ip(req)
        user_agent = shorten_user_agent(get_request_user_agent(req))
        if req.path == '/api/admin/login/':  # 登录时去除密码明文
            resource = 'admin_login'
            operator = resp['id']
            temp = json.loads(content)
            temp.pop('password')
            content = json.dumps(temp)
        elif resource == 'admin_user_add':  # 新增用户时，去除密码明文
            temp = json.loads(content)
            temp.pop('password')
            content = json.dumps(temp)

        from gis.admin.services import admin_service

        admin_service.insert_record(resource, resource_id, action, content, operator, ip, user_agent)
    except Exception as e:
        _LOGGER.exception("insert record exception {}".format(e))
